/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.deliveryticket.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.FndEventTypeBase;
import com.lightkits.common.db.entity.FndOrganizationBase;
import com.lightkits.common.db.entity.FndPartyBase;
import com.lightkits.common.db.entity.FndPartySiteBase;
import com.lightkits.common.db.entity.FndWorker;
import com.lightkits.common.db.entity.WmDeliveryTicket;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.json.JsonUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.framework.soa.client.id.GetGlobalIDRequestType;
import com.lightkits.framework.soa.client.id.GetGlobalIDResponseType;
import com.lightkits.framework.soa.client.id.IDServiceClient;
import com.lightkits.wms.client.DocumentServiceClient;
import com.lightkits.wms.domain.deliveryorder.service.CreateDeliveryOrderDomain;
import com.lightkits.wms.domain.deliveryticket.service.SaveTicketHeadDomain;
import com.lightkits.wms.domain.rawmatstorage.repo.WmDeliveyTicketService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventRecordService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventService;
import com.lightkits.wms.domain.usuallyinterface.GetWmMoveTypeExecutor;
import com.lightkits.wms.dto.deliveryticket.models.TicketHeadDTO;
import com.lightkits.wms.dto.document.GenerateDocNumRequestType;
import com.lightkits.wms.dto.document.GenerateDocNumResponseType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * SaveTicketHeadDomianImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/4/22 17:31
 */
@Service
public class SaveTicketHeadDomianImpl implements SaveTicketHeadDomain {
    private final WmDeliveyTicketService wmDeliveryTicket;
    private final Logger logger = LoggerFactory.getLogger(GetWmMoveTypeExecutor.class);

    private final IDServiceClient idAdapterService;

    private final BdEventService bdEventService;
    private final BdEventRecordService bdEventRecordService;

    private final DocumentServiceClient client;

    @Autowired
    public SaveTicketHeadDomianImpl(WmDeliveyTicketService wmDeliveryTicket,
                                    IDServiceClient idAdapterService,
                                    BdEventService bdEventService,
                                    BdEventRecordService bdEventRecordService,
                                    DocumentServiceClient client) {
        this.wmDeliveryTicket = wmDeliveryTicket;
        this.idAdapterService = idAdapterService;
        this.bdEventService = bdEventService;
        this.bdEventRecordService = bdEventRecordService;
        this.client = client;
    }

    /**
     * 送货单头参数校验
     *
     * @param dto 送货单头信息
     * @return IResult
     */
    private IResult checkParams(TicketHeadDTO dto) {
        try {
            //参数非空校验
            IntegrityValidator.begin()
                    .validate(dto.getOrgId(), "Organization Id")
                    .validate(dto.getPartyId(), "Party Id")
                    .validate(dto.getReceiveWorkerId(), "Receive Worker Id");
            //参数有效性校验
            TransactionValidate check1 = TransactionValidate.beginValidity(FndOrganizationBase.class);
            check1.checkIdValidity(ObjectUtil.toString(dto.getOrgId()), "ORGANIZATION_ID");

            check1 = TransactionValidate.beginValidity(FndPartyBase.class);
            check1.checkIdValidity(ObjectUtil.toString(dto.getPartyId()), "ID");

            check1 = TransactionValidate.beginValidity(FndWorker.class);
            check1.checkIdValidity(ObjectUtil.toString(dto.getReceiveWorkerId()), "ID");

            check1 = TransactionValidate.beginValidity(FndPartySiteBase.class);
            check1.checkIdValidity(ObjectUtil.toString(dto.getPartySiteId()), "ID");

        } catch (LightKitsBizException e) {
            return e.result();
        }
        return IResult.success();
    }

    /**
     * 创建送货单头
     *
     * @param dto 送货单头信息
     * @return WmDeliveryTicket
     */
    private CheckResult<WmDeliveryTicket> createTicketHead(TicketHeadDTO dto) {
        CheckResult<WmDeliveryTicket> checkResult = new CheckResult<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        checkResult.setSuccessful(true);
        WmDeliveryTicket ticketHead = new WmDeliveryTicket();
        ticketHead.setOrganizationId(ParseUtil.tryLongWithException(dto.getOrgId()));
        ticketHead.setPartyId(ParseUtil.tryLongWithException(dto.getPartyId()));
        ticketHead.setTicketType(dto.getTicketType());
        ticketHead.setTicketStatus("NEW");
        //创建送货单
        GenerateDocNumRequestType request = new GenerateDocNumRequestType();
        request.setCount(1);
        request.setSize(5);
        request.setType("DT");
        request.setField1(df.format(new Date()));
        GenerateDocNumResponseType response = client.generateDocNumber(request);
        ticketHead.setTicketNum(response.getDocNumList().get(0));
        if (!ObjectUtil.isNullOrEmpty(dto.getBuyerId())) {
            ticketHead.setBuyerId(ParseUtil.tryLongWithException(dto.getBuyerId()));
        }
        ticketHead.setReceiveWorkerId(ParseUtil.tryLongWithException(dto.getReceiveWorkerId()));
        if (!ObjectUtil.isNullOrEmpty(dto.getPartySiteId())) {
            ticketHead.setPartySiteId(ParseUtil.tryLongWithException(dto.getPartySiteId()));
        }
        ticketHead.setRemark(dto.getRemark());

        //创建送货单创建事件（"DELIVERY_TICKET_NEW"）
        List<BdEvent> events = new ArrayList<>();
        CheckResult<BdEvent> eventCheckResult = this.createEvent(dto);
        if (!eventCheckResult.isSuccessful()) {
            checkResult.setSuccessful(false);
            checkResult.setMessage(eventCheckResult.getMessage());
            return checkResult;
        }
        events.add(eventCheckResult.getData());
        ticketHead.store(events);
        checkResult.setData(ticketHead);
        return checkResult;
    }

    /**
     * 创建送货单头事件
     *
     * @param dto 送货单头参数
     * @return BdEvent
     */
    private CheckResult<BdEvent> createEvent(TicketHeadDTO dto) {
        CheckResult<BdEvent> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        if (ObjectUtil.isEmpty(dto.getEventRequestId()) || dto.getEventRequestId() == 0) {
            GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
            idRequest.setCount(1);
            GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
            Iterator<Long> sfIds = idResponse.getIds().iterator();
            dto.setEventRequestId(sfIds.next());
        }
        BdEvent event = new BdEvent();
        event.setWorkerId(ParseUtil.tryLongWithException(dto.getReceiveWorkerId()));
        event.setRemark(dto.getRemark());
        event.setParentEventId(dto.getParentEventId());
        event.setOrganizationId(ParseUtil.tryLongWithException(dto.getOrgId()));
        event.setEventRequestId(dto.getEventRequestId());
        //送货单新建事件
        event.setEventTypeCode("DELIVERY_TICKET_NEW");
        FndEventTypeBase eventTypeBase = new FndEventTypeBase().selectOne(new EntityWrapper()
                .eq(FndEventTypeBase.EVENT_TYPE_CODE, "DELIVERY_TICKET_NEW"));
        event.setEventTypeId(eventTypeBase.getId());

        //Create Record
        List<BdEventRecord> records = new ArrayList<>();
        BdEventRecord record = this.createRecord("DELIVERY_TICKET");
        records.add(record);

        event.store(records);
        checkResult.setData(event);
        return checkResult;
    }

    /**
     * 创建送货单快照
     *
     * @param objectType 对象类型
     * @return BdEventRecord
     */
    private BdEventRecord createRecord(String objectType) {
        BdEventRecord record = new BdEventRecord();

        record.setObjectType(objectType);

        return record;
    }

    /**
     * 创建送货单头
     *
     * @param dto 送货单头参数
     * @return map
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckResult<Map<String, String>> saveTicketHead(TicketHeadDTO dto) {
        CheckResult<Map<String, String>> result = new CheckResult<>();
        result.setSuccessful(true);

        //校验送货单头参数
        this.checkParams(dto).fill(result);
        if (!result.isSuccessful()) {
            return result;
        }
        //创建送货单头
        CheckResult<WmDeliveryTicket> checkResult = this.createTicketHead(dto);
        if (!checkResult.isSuccessful()) {
            return checkResult.fill(result);
        }
        WmDeliveryTicket ticketHead = checkResult.getData();
        //送货单头插入数据库
        boolean headFlag = wmDeliveryTicket.insert(ticketHead);
        if (!headFlag) {
            throw new LightKitsBizException("Save Delivery Head error.");
        }
        //创建送货单头事件
        List<BdEvent> events = new ArrayList<>();
        List<Object> bdEvents = ticketHead.take();
        for (Object object : bdEvents) {
            if (object.getClass().equals(BdEvent.class)) {
                BdEvent event = (BdEvent) object;
                events.add(event);
            }
        }
        boolean insertEventFlag = bdEventService.insertBatch(events);
        if (!insertEventFlag) {
            throw new LightKitsBizException("Save events error.");
        }
        //创建送货单快照并插入
        List<BdEventRecord> bdEventRecords = new ArrayList<>();
        for (BdEvent event : events) {
            List<Object> records = event.take();
            for (Object object : records) {
                if (object.getClass().equals(BdEventRecord.class)) {
                    BdEventRecord record = (BdEventRecord) object;
                    record.setEventId(event.getId());
                    record.setSnapshotRecord(JsonUtil.toString(ticketHead));
                    record.setObjectId(ticketHead.getId());
                    bdEventRecords.add(record);
                }
            }
        }
        boolean insertRecordsFlag = bdEventRecordService.insertBatch(bdEventRecords);
        if (!insertRecordsFlag) {
            throw new LightKitsBizException("Save eventRecords error.");
        }
        //返回送货单头ID和送货单创建事件ID
        Map<String, String> res = new HashMap<>();
        res.put("ticketHeadId", ticketHead.getId().toString());
        res.put("eventId", events.get(0).getId().toString());
        result.setData(res);
        return result;
    }


}
